Module 15 Multiple Regression and ANCOVA

R = matrix(cbind(1, 0.8, -0.5, 0, 0.8, 1, -0.3, 0.3, -0.5, -0.3, 1, 0.6, 0,
    0.3, 0.6, 1), nrow = 4)
n <- 1000
k <- 4
M <- NULL
V <- NULL
mu <- c(15, 40, 5, 23)  # vector of variable means
s <- c(5, 20, 4, 15)  # vector of variable SDs
for (i in 1:k) {
    V <- rnorm(n, mu[i], s[i])
    M <- cbind(M, V)
}
M <- matrix(M, nrow = n, ncol = k)
orig <- as.data.frame(M)
names(orig) = c("Y", "X1", "X2", "X3")
head(orig)
##           Y         X1         X2         X3
## 1 10.789676  7.9721672  5.2036591  13.872677
## 2  8.932434 75.7880384  7.4068599  29.533060
## 3 15.013207 51.2004587 10.4151323   6.756778
## 4 19.121711 48.8518779  4.8960257  28.101257
## 5 15.177670 -0.8254089  7.3178741   8.504210
## 6 15.828277 75.7393465  0.3584238 -15.735571
cor(orig)
##              Y          X1          X2          X3
## Y   1.00000000  0.02007344 -0.00190345 -0.03394157
## X1  0.02007344  1.00000000 -0.04810534 -0.02557318
## X2 -0.00190345 -0.04810534  1.00000000  0.06401337
## X3 -0.03394157 -0.02557318  0.06401337  1.00000000
plot(orig)

ms <- apply(orig, 2, FUN = "mean") 
ms
##         Y        X1        X2        X3 
## 15.123685 39.690855  5.031446 23.183481
sds <- apply(orig, 2, FUN = "sd")
sds
##         Y        X1        X2        X3 
##  5.018583 20.307670  3.916493 14.716197
normalized <- sweep(orig, 2, STATS = ms, FUN = "-")  # 2nd dimension is columns, removing array of means, function = subtract
normalized <- sweep(normalized, 2, STATS = sds, FUN = "/")  # 2nd dimension is columns, scaling by array of sds, function = divide
head(normalized)  # now a dataframe of Z scores
##             Y         X1          X2         X3
## 1 -0.86359212 -1.5619068  0.04397113 -0.6326909
## 2 -1.23366504  1.7775148  0.60651535  0.4314688
## 3 -0.02201366  0.5667614  1.37461886 -1.1162329
## 4  0.79664445  0.4511115 -0.03457706  0.3341744
## 5  0.01075713 -1.9951213  0.58379458 -0.9974908
## 6  0.14039667  1.7751171 -1.19316494 -2.6446405
M <- as.matrix(normalized)
U = chol(R)
newM = M %*% U
new = as.data.frame(newM)
names(new) = c("Y", "X1", "X2", "X3")
cor(new)
##              Y         X1         X2          X3
## Y   1.00000000  0.8043311 -0.5021422 -0.01203612
## X1  0.80433111  1.0000000 -0.3285746  0.26045570
## X2 -0.50214220 -0.3285746  1.0000000  0.61546733
## X3 -0.01203612  0.2604557  0.6154673  1.00000000
plot(orig)

plot(new)

df <- sweep(new, 2, STATS = sds, FUN = "*")  # scale back out to original mean...
df <- sweep(df, 2, STATS = ms, FUN = "+")  # and standard deviation
head(df)
##           Y        X1        X2        X3
## 1 10.789676  6.629608  5.849393  6.341751
## 2  8.932434 41.306875 10.626251 45.605142
## 3 15.013207 46.238980 10.019761 29.521066
## 4 19.121711 58.129863  3.650797 29.226502
## 5 15.177670 15.555859  5.651158  4.672821
## 6 15.828277 63.600853  1.943915  1.566435
cor(df)
##              Y         X1         X2          X3
## Y   1.00000000  0.8043311 -0.5021422 -0.01203612
## X1  0.80433111  1.0000000 -0.3285746  0.26045570
## X2 -0.50214220 -0.3285746  1.0000000  0.61546733
## X3 -0.01203612  0.2604557  0.6154673  1.00000000
plot(df)

Challenge 1

library(ggplot2)
require(gridExtra)
g1 <- ggplot(data = df, aes(x = X1, y = Y)) + geom_point() + geom_smooth(method = "lm",
    formula = y ~ x)
g2 <- ggplot(data = df, aes(x = X2, y = Y)) + geom_point() + geom_smooth(method = "lm",
    formula = y ~ x)
g3 <- ggplot(data = df, aes(x = X3, y = Y)) + geom_point() + geom_smooth(method = "lm",
    formula = y ~ x)
grid.arrange(g1, g2, g3, ncol = 3)

m1 <- lm(data = df, formula = Y ~ X1)
summary(m1)
## 
## Call:
## lm(formula = Y ~ X1, data = df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -11.655  -2.032  -0.072   2.008   8.084 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 7.309177   0.205652   35.54   <2e-16 ***
## X1          0.196884   0.004604   42.76   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.983 on 998 degrees of freedom
## Multiple R-squared:  0.6469, Adjusted R-squared:  0.6466 
## F-statistic:  1829 on 1 and 998 DF,  p-value: < 2.2e-16
m2 <- lm(data = df, formula = Y ~ X2)
summary(m2)
## 
## Call:
## lm(formula = Y ~ X2, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.7243  -2.8832   0.0466   3.1809  13.0697 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 18.38628    0.22470   81.83   <2e-16 ***
## X2          -0.64844    0.03535  -18.34   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.342 on 998 degrees of freedom
## Multiple R-squared:  0.2521, Adjusted R-squared:  0.2514 
## F-statistic: 336.5 on 1 and 998 DF,  p-value: < 2.2e-16
m3 <- lm(data = df, formula = Y ~ X3)
summary(m3)
## 
## Call:
## lm(formula = Y ~ X3, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -13.5165  -3.5764   0.1243   3.5487  15.4947 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 15.218702   0.296048   51.41   <2e-16 ***
## X3          -0.004098   0.010778   -0.38    0.704    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.021 on 998 degrees of freedom
## Multiple R-squared:  0.0001449,  Adjusted R-squared:  -0.000857 
## F-statistic: 0.1446 on 1 and 998 DF,  p-value: 0.7038
m <- lm(data = df, formula = Y ~ X1 + X2 + X3)
coef(m)
## (Intercept)          X1          X2          X3 
##  9.68859064  0.18696066 -0.25223185 -0.03090319
summary(m)
## 
## Call:
## lm(formula = Y ~ X1 + X2 + X3, data = df)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11.5103  -1.7952  -0.0694   1.8003   7.7340 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  9.688591   0.261698  37.022  < 2e-16 ***
## X1           0.186961   0.005611  33.321  < 2e-16 ***
## X2          -0.252232   0.036261  -6.956 6.33e-12 ***
## X3          -0.030903   0.009354  -3.304 0.000987 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.69 on 996 degrees of freedom
## Multiple R-squared:  0.7135, Adjusted R-squared:  0.7126 
## F-statistic: 826.9 on 3 and 996 DF,  p-value: < 2.2e-16
plot(fitted(m), residuals(m))

hist(residuals(m))

qqnorm(residuals(m))

f <- (summary(m)$r.squared * (nrow(df) - (ncol(df) - 1) - 1))/((1 - summary(m)$r.squared) *
    (ncol(df) - 1))
f
## [1] 826.8652

Challenge 2

library(curl)
f <- curl("https://raw.githubusercontent.com/fuzzyatelin/fuzzyatelin.github.io/master/AN588_Fall21/zombies.csv")
z <- read.csv(f, header = TRUE, sep = ",", stringsAsFactors = TRUE)
head(z)
##   id first_name last_name gender   height   weight zombies_killed
## 1  1      Sarah    Little Female 62.88951 132.0872              2
## 2  2       Mark    Duncan   Male 67.80277 146.3753              5
## 3  3    Brandon     Perez   Male 72.12908 152.9370              1
## 4  4      Roger   Coleman   Male 66.78484 129.7418              5
## 5  5      Tammy    Powell Female 64.71832 132.4265              4
## 6  6    Anthony     Green   Male 71.24326 152.5246              1
##   years_of_education                           major      age
## 1                  1                medicine/nursing 17.64275
## 2                  3 criminal justice administration 22.58951
## 3                  1                       education 21.91276
## 4                  6                  energy studies 18.19058
## 5                  3                       logistics 21.10399
## 6                  4                  energy studies 21.48355
m <- lm(data = z, height ~ weight + age)
summary(m)
## 
## Call:
## lm(formula = height ~ weight + age, data = z)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.2278 -1.1782 -0.0574  1.1566  5.4117 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 31.763388   0.470797   67.47   <2e-16 ***
## weight       0.163107   0.002976   54.80   <2e-16 ***
## age          0.618270   0.018471   33.47   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.64 on 997 degrees of freedom
## Multiple R-squared:  0.8555, Adjusted R-squared:  0.8553 
## F-statistic:  2952 on 2 and 997 DF,  p-value: < 2.2e-16

ANCOVA

library(car)
## Loading required package: carData
m <- lm(data = z, formula = height ~ gender + age)
summary(m)
## 
## Call:
## lm(formula = height ~ gender + age, data = z)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -10.1909  -1.7173   0.1217   1.7670   7.6746 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 46.74251    0.56869   82.19   <2e-16 ***
## genderMale   4.00224    0.16461   24.31   <2e-16 ***
## age          0.94091    0.02777   33.88   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.603 on 997 degrees of freedom
## Multiple R-squared:  0.6361, Adjusted R-squared:  0.6354 
## F-statistic: 871.5 on 2 and 997 DF,  p-value: < 2.2e-16
m.aov <- Anova(m, type = "II")
m.aov
## Anova Table (Type II tests)
## 
## Response: height
##           Sum Sq  Df F value    Pr(>F)    
## gender    4003.9   1  591.15 < 2.2e-16 ***
## age       7775.6   1 1148.01 < 2.2e-16 ***
## Residuals 6752.7 997                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(fitted(m), residuals(m))

hist(residuals(m))

qqnorm(residuals(m))

library(ggplot2)
p <- ggplot(data = z, aes(x = age, y = height)) + geom_point(aes(color = factor(gender))) +
    scale_color_manual(values = c("goldenrod", "blue"))
p <- p + geom_abline(slope = m$coefficients[3], intercept = m$coefficients[1],
    color = "goldenrod4")
p <- p + geom_abline(slope = m$coefficients[3], intercept = m$coefficients[1] +
    m$coefficients[2], color = "darkblue")
p

CI and Prediction

m <- lm(data = z, formula = height ~ age + gender)
summary(m)
## 
## Call:
## lm(formula = height ~ age + gender, data = z)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -10.1909  -1.7173   0.1217   1.7670   7.6746 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 46.74251    0.56869   82.19   <2e-16 ***
## age          0.94091    0.02777   33.88   <2e-16 ***
## genderMale   4.00224    0.16461   24.31   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.603 on 997 degrees of freedom
## Multiple R-squared:  0.6361, Adjusted R-squared:  0.6354 
## F-statistic: 871.5 on 2 and 997 DF,  p-value: < 2.2e-16
confint(m, level = 0.95)
##                  2.5 %     97.5 %
## (Intercept) 45.6265330 47.8584809
## age          0.8864191  0.9954081
## genderMale   3.6792172  4.3252593

Challenge 3

ci <- predict(m, newdata = data.frame(age = 29, gender = "Male"), interval = "confidence",
    level = 0.95)
ci
##        fit      lwr      upr
## 1 78.03124 77.49345 78.56903
pi <- predict(m, newdata = data.frame(age = 29, gender = "Male"), interval = "prediction",
    level = 0.95)
pi
##        fit      lwr      upr
## 1 78.03124 72.89597 83.16651

Interactions between Predictions

m <- lm(data = z, height ~ age + gender + age:gender)  # or
summary(m)
## 
## Call:
## lm(formula = height ~ age + gender + age:gender, data = z)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9.7985 -1.6973  0.1189  1.7662  7.9473 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    48.18107    0.79839  60.348   <2e-16 ***
## age             0.86913    0.03941  22.053   <2e-16 ***
## genderMale      1.15975    1.12247   1.033   0.3018    
## age:genderMale  0.14179    0.05539   2.560   0.0106 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.595 on 996 degrees of freedom
## Multiple R-squared:  0.6385, Adjusted R-squared:  0.6374 
## F-statistic: 586.4 on 3 and 996 DF,  p-value: < 2.2e-16
m <- lm(data = z, height ~ age * gender)
summary(m)
## 
## Call:
## lm(formula = height ~ age * gender, data = z)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9.7985 -1.6973  0.1189  1.7662  7.9473 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    48.18107    0.79839  60.348   <2e-16 ***
## age             0.86913    0.03941  22.053   <2e-16 ***
## genderMale      1.15975    1.12247   1.033   0.3018    
## age:genderMale  0.14179    0.05539   2.560   0.0106 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.595 on 996 degrees of freedom
## Multiple R-squared:  0.6385, Adjusted R-squared:  0.6374 
## F-statistic: 586.4 on 3 and 996 DF,  p-value: < 2.2e-16
coefficients(m)
##    (Intercept)            age     genderMale age:genderMale 
##     48.1810741      0.8691284      1.1597481      0.1417928
library(ggplot2)
library(gridExtra)
p1 <- ggplot(data = z, aes(x = age, y = height)) + geom_point(aes(color = factor(gender))) +
    scale_color_manual(values = c("goldenrod", "blue"))
p1 <- p1 + geom_abline(slope = m$coefficients[2], intercept = m$coefficients[1],
    color = "goldenrod4")
p1 <- p1 + geom_abline(slope = m$coefficients[2] + m$coefficients[4], intercept = m$coefficients[1] +
    m$coefficients[3], color = "darkblue")
p1

p2 <- ggplot(data = z, aes(x = age, y = height)) + geom_point(aes(color = factor(gender))) +
    scale_color_manual(values = c("goldenrod", "blue")) + geom_smooth(method = "lm",
    aes(color = factor(gender), fullrange = TRUE))
## Warning in geom_smooth(method = "lm", aes(color = factor(gender), fullrange =
## TRUE)): Ignoring unknown aesthetics: fullrange
grid.arrange(p1, p2, ncol = 2)
## `geom_smooth()` using formula = 'y ~ x'

Challenge 4

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
## 
##     recode
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
f <- curl("https://raw.githubusercontent.com/fuzzyatelin/fuzzyatelin.github.io/master/AN588_Fall21/KamilarAndCooperData.csv")
d <- read.csv(f, header = TRUE, sep = ",", stringsAsFactors = TRUE)
head(d)
##               Scientific_Name          Family          Genus      Species
## 1 Allenopithecus_nigroviridis Cercopithecidae Allenopithecus nigroviridis
## 2         Allocebus_trichotis Cercopithecidae      Allocebus    trichotis
## 3           Alouatta_belzebul        Atelidae       Alouatta     belzebul
## 4             Alouatta_caraya        Atelidae       Alouatta       caraya
## 5            Alouatta_guariba        Atelidae       Alouatta      guariba
## 6           Alouatta_palliata        Atelidae       Alouatta     palliata
##   Brain_Size_Species_Mean Brain_Size_Female_Mean   Brain_size_Ref
## 1                   58.02                  53.70 Isler et al 2008
## 2                      NA                     NA                 
## 3                   52.84                  51.19 Isler et al 2008
## 4                   52.63                  47.80 Isler et al 2008
## 5                   51.70                  49.08 Isler et al 2008
## 6                   49.88                  48.04 Isler et al 2008
##   Body_mass_male_mean Body_mass_female_mean Mass_Dimorphism
## 1                6130                  3180           1.928
## 2                  92                    84           1.095
## 3                7270                  5520           1.317
## 4                6525                  4240           1.539
## 5                5800                  4550           1.275
## 6                7150                  5350           1.336
##                 Mass_Ref MeanGroupSize AdultMales AdultFemale AdultSexRatio
## 1       Isler et al 2008            NA         NA          NA            NA
## 2 Smith and Jungers 1997          1.00       1.00         1.0            NA
## 3       Isler et al 2008          7.00       1.00         1.0          1.00
## 4       Isler et al 2008          8.00       2.30         3.3          1.43
## 5       Isler et al 2008          6.53       1.37         2.2          1.61
## 6       Isler et al 2008         12.00       2.90         6.3          2.17
##                                                     Social_Organization_Ref
## 1                                                                          
## 2                                                             Kappeler 1997
## 3                                                       Campbell et al 2007
## 4 van Schaik et al. 1999; Kappeler and Pereira 2003; Nunn & van Schaik 2000
## 5                                                       Campbell et al 2007
## 6 van Schaik et al. 1999; Kappeler and Pereira 2003; Nunn & van Schaik 2000
##   InterbirthInterval_d Gestation WeaningAge_d MaxLongevity_m LitterSz
## 1                   NA        NA       106.15          276.0     1.01
## 2                   NA        NA           NA             NA     1.00
## 3                   NA        NA           NA             NA       NA
## 4               337.62       187       323.16          243.6     1.01
## 5                   NA        NA           NA             NA       NA
## 6               684.37       186       495.60          300.0     1.02
##    Life_History_Ref GR_MidRangeLat_dd Precip_Mean_mm Temp_Mean_degC AET_Mean_mm
## 1 Jones et al. 2009             -0.17         1574.0           25.2      1517.8
## 2                              -16.59         1902.3           20.3      1388.2
## 3                               -6.80         1643.5           24.9      1286.6
## 4 Jones et al. 2009            -20.34         1166.4           22.9      1193.1
## 5                              -21.13         1332.3           19.6      1225.7
## 6 Jones et al. 2009              6.95         1852.6           23.7      1300.0
##   PET_Mean_mm       Climate_Ref HomeRange_km2      HomeRangeRef DayLength_km
## 1      1589.4 Jones et al. 2009            NA                             NA
## 2      1653.7 Jones et al. 2009            NA                             NA
## 3      1549.8 Jones et al. 2009            NA                             NA
## 4      1404.9 Jones et al. 2009            NA                           0.40
## 5      1332.2 Jones et al. 2009          0.03 Jones et al. 2009           NA
## 6      1633.9 Jones et al. 2009          0.19 Jones et al. 2009         0.32
##       DayLengthRef Territoriality Fruit Leaves Fauna             DietRef1
## 1                              NA    NA                                  
## 2                              NA    NA                                  
## 3                              NA  57.3   19.1   0.0 Campbell et al. 2007
## 4 Nunn et al. 2003             NA  23.8   67.7   0.0 Campbell et al. 2007
## 5                              NA   5.2   73.0   0.0 Campbell et al. 2007
## 6 Nunn et al. 2003         0.6506  33.1   56.4   0.0 Campbell et al. 2007
##   Canine_Dimorphism Canine_Dimorphism_Ref  Feed  Move  Rest Social
## 1             2.210   Plavcan & Ruff 2008    NA    NA    NA     NA
## 2                NA                          NA    NA    NA     NA
## 3             1.811   Plavcan & Ruff 2008 13.75 18.75 57.30  10.00
## 4             1.542   Plavcan & Ruff 2008 15.90 17.60 61.60   4.90
## 5             1.783   Plavcan & Ruff 2008 18.33 14.33 64.37   3.00
## 6             1.703   Plavcan & Ruff 2008 17.94 12.32 66.14   3.64
##    Activity_Budget_Ref
## 1                     
## 2                     
## 3 Campbell et al. 2007
## 4 Campbell et al. 2007
## 5 Campbell et al. 2007
## 6 Campbell et al. 2007
d <- select(d, Brain_Size_Female_Mean, Family, Body_mass_female_mean, MeanGroupSize,
    DayLength_km, HomeRange_km2, Move)
m <- lm(data = d, log(HomeRange_km2) ~ log(Body_mass_female_mean) + log(Brain_Size_Female_Mean) +
    MeanGroupSize + Move)
summary(m)
## 
## Call:
## lm(formula = log(HomeRange_km2) ~ log(Body_mass_female_mean) + 
##     log(Brain_Size_Female_Mean) + MeanGroupSize + Move, data = d)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.7978 -0.6473 -0.0038  0.8807  2.1598 
## 
## Coefficients:
##                              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                 -6.955853   1.957472  -3.553 0.000865 ***
## log(Body_mass_female_mean)   0.315276   0.468439   0.673 0.504153    
## log(Brain_Size_Female_Mean)  0.614460   0.591100   1.040 0.303771    
## MeanGroupSize                0.034026   0.009793   3.475 0.001095 ** 
## Move                         0.025916   0.019559   1.325 0.191441    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.127 on 48 degrees of freedom
##   (160 observations deleted due to missingness)
## Multiple R-squared:  0.6359, Adjusted R-squared:  0.6055 
## F-statistic: 20.95 on 4 and 48 DF,  p-value: 4.806e-10
plot(m$residuals)

qqnorm(m$residuals)

shapiro.test(m$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  m$residuals
## W = 0.96517, p-value = 0.1242
m <- lm(data = d, log(HomeRange_km2) ~ log(Body_mass_female_mean) + log(Brain_Size_Female_Mean) +
    MeanGroupSize)
summary(m)
## 
## Call:
## lm(formula = log(HomeRange_km2) ~ log(Body_mass_female_mean) + 
##     log(Brain_Size_Female_Mean) + MeanGroupSize, data = d)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.7982 -0.7310 -0.0140  0.8386  3.1926 
## 
## Coefficients:
##                              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                 -5.354845   1.176046  -4.553 1.45e-05 ***
## log(Body_mass_female_mean)  -0.181627   0.311382  -0.583 0.560972    
## log(Brain_Size_Female_Mean)  1.390536   0.398840   3.486 0.000721 ***
## MeanGroupSize                0.030433   0.008427   3.611 0.000473 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.228 on 103 degrees of freedom
##   (106 observations deleted due to missingness)
## Multiple R-squared:  0.6766, Adjusted R-squared:  0.6672 
## F-statistic: 71.85 on 3 and 103 DF,  p-value: < 2.2e-16
plot(m$residuals)

qqnorm(m$residuals)

shapiro.test(m$residuals)  # no significant deviation from normal
## 
##  Shapiro-Wilk normality test
## 
## data:  m$residuals
## W = 0.99366, p-value = 0.9058